package net.yienyien.process.bpmn2bpel.test;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import javax.wsdl.WSDLException;
import javax.wsdl.xml.WSDLWriter;


import net.yienyien.process.bpd.BPDModel;
import net.yienyien.process.bpd.BpdPackage;
import net.yienyien.process.bpd.transducer.ProviderException;
import net.yienyien.process.bpel.generator.BPELGenerationException;
import net.yienyien.process.bpel.generator.BPELGenerator;
import net.yienyien.process.bpel.generator.Production;
import net.yienyien.process.bpel.generator.controlFlow.ControlFlowContrib;
import net.yienyien.process.bpel.generator.dataFlow.DataFlowContrib;
import net.yienyien.process.bpel.generator.init.InitContrib;
import net.yienyien.process.bpel.generator.partner.PartnerContrib;
import net.yienyien.process.dfm.DfmPackage;
import net.yienyien.process.dfm4bpmn.DataFlow;
import net.yienyien.process.dfm4bpmn.Dfm4bpmnPackage;
import net.yienyien.process.pim.PimPackage;
import net.yienyien.process.pmm.PmmPackage;
import net.yienyien.process.pmm4bpmn.Bindings;
import net.yienyien.process.pmm4bpmn.Pmm4bpmnPackage;
import net.yienyien.process2bpel.bpmn2bpd.BPMN2BPD;

import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.URIConverter;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;
import org.eclipse.emf.ecore.xmi.impl.XMLResourceFactoryImpl;
import org.eclipse.stp.bpmn.BpmnDiagram;
import org.eclipse.stp.bpmn.BpmnPackage;
import org.eclipse.wst.wsdl.Definition;
import org.eclipse.wst.wsdl.WSDLFactory;
import org.eclipse.wst.wsdl.WSDLPackage;
import org.eclipse.wst.wsdl.binding.http.HTTPPackage;
import org.eclipse.wst.wsdl.binding.soap.SOAPPackage;
import org.eclipse.wst.wsdl.internal.util.WSDLResourceFactoryImpl;
import org.eclipse.wst.wsdl.util.WSDLResourceImpl;
import org.open.oasis.docs.wsbpel._2._0.plnktype.PlnktypePackage;
import org.open.oasis.docs.wsbpel._2._0.process.abstract_.AbstractFactory;
import org.open.oasis.docs.wsbpel._2._0.process.abstract_.AbstractPackage;
import org.open.oasis.docs.wsbpel._2._0.process.abstract_.DocumentRoot;
import org.open.oasis.docs.wsbpel._2._0.process.abstract_.TProcess;
import org.open.oasis.docs.wsbpel._2._0.process.abstract_.util.AbstractResourceFactoryImpl;
import org.open.oasis.docs.wsbpel._2._0.process.abstract_.util.AbstractXMLProcessor;

import com.ibm.wsdl.xml.WSDLWriterImpl;

public class Main {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		PimPackage.eINSTANCE.eClass();
		PmmPackage.eINSTANCE.eClass();
		BpmnPackage.eINSTANCE.eClass();
		BpdPackage.eINSTANCE.eClass();
		WSDLPackage.eINSTANCE.eClass();
		SOAPPackage.eINSTANCE.eClass();
		HTTPPackage.eINSTANCE.eClass();
		Pmm4bpmnPackage.eINSTANCE.eClass();
		AbstractPackage.eINSTANCE.eClass();
		PlnktypePackage.eINSTANCE.eClass();
		Dfm4bpmnPackage.eINSTANCE.eClass();
		DfmPackage.eINSTANCE.eClass();
		
		BPELGenerator generator=new BPELGenerator();
		HashMap<String, EObject> arg=new HashMap<String,EObject>();
		
		ResourceSet set=new ResourceSetImpl();
		
		set.getResourceFactoryRegistry().getExtensionToFactoryMap().put("bpmn", new XMIResourceFactoryImpl());
		set.getResourceFactoryRegistry().getExtensionToFactoryMap().put("pim", new XMIResourceFactoryImpl());
		set.getResourceFactoryRegistry().getExtensionToFactoryMap().put("pmm4bpmn", new XMIResourceFactoryImpl());
		set.getResourceFactoryRegistry().getExtensionToFactoryMap().put("bpel", new AbstractResourceFactoryImpl());
		set.getResourceFactoryRegistry().getExtensionToFactoryMap().put("wsdl", new WSDLResourceFactoryImpl());
		set.getResourceFactoryRegistry().getExtensionToFactoryMap().put("dfm4bpmn", new XMIResourceFactoryImpl());
		
		/*
		set.getURIConverter().getURIMap().put(URI.createURI("utp.bpmn"), URI.createURI("tmp/utp.bpmn"));
		set.getURIConverter().getURIMap().put(URI.createURI("utp.pim"), URI.createURI("tmp/utp.pim"));
		set.getURIConverter().getURIMap().put(URI.createURI("utp.pmm4bpmn"), URI.createURI("tmp/utp.pmm4bpmn"));
		set.getURIConverter().getURIMap().put(URI.createURI("Service1.wsdl"), URI.createURI("tmp/Service1.wsdl"));
		set.getURIConverter().getURIMap().put(URI.createURI("Service2.wsdl"), URI.createURI("tmp/Service2.wsdl"));
		URI bpmnURI=URI.createURI("utp.bpmn");		
		URI pimURI=URI.createURI("utp.pim");
		URI pmmURI=URI.createURI("utp.pmm4bpmn");
		URI service1URI=URI.createURI("Service1.wsdl");
		URI service2URI=URI.createURI("Service2.wsdl");
		*/
		
		URI bpmnURI=URI.createURI("complaint.bpmn");		
		URI pimURI=URI.createURI("complaint.pim");
		URI pmmURI=URI.createURI("complaint.pmm4bpmn");
		URI servURI=URI.createURI("complaint.wsdl");
		URI service1URI=URI.createURI("ComplaintS1.wsdl");
		URI service2URI=URI.createURI("ComplaintS2.wsdl");
		URI dfmURI=URI.createURI("complaint.dfm4bpmn");
		
		set.getURIConverter().getURIMap().put(bpmnURI, URI.createURI("tmp/complaint.bpmn"));
		set.getURIConverter().getURIMap().put(pimURI, URI.createURI("tmp/complaint.pim"));
		set.getURIConverter().getURIMap().put(pmmURI, URI.createURI("tmp/complaint.pmm4bpmn"));
		set.getURIConverter().getURIMap().put(servURI, URI.createURI("tmp/complaint.wsdl"));
		set.getURIConverter().getURIMap().put(service1URI, URI.createURI("tmp/ComplaintS1.wsdl"));
		set.getURIConverter().getURIMap().put(service2URI, URI.createURI("tmp/ComplaintS2.wsdl"));
		set.getURIConverter().getURIMap().put(dfmURI, URI.createURI("tmp/complaint.dfm4bpmn"));
		

		Resource bpmnR=set.getResource(bpmnURI, true);
		Resource pimR=set.getResource(pimURI, true);
		Resource pmmR=set.getResource(pmmURI, true);
		Resource dfmR=set.getResource(dfmURI, true);

		WSDLResourceImpl service=new WSDLResourceImpl(servURI);
		WSDLResourceImpl service1R=new WSDLResourceImpl(service1URI);
		WSDLResourceImpl service2R=new WSDLResourceImpl(service2URI);
		
		
		
		set.getResources().add(service);
		set.getResources().add(service1R);
		set.getResources().add(service2R);
		
		try {
			service.load(null);
			service1R.load(null);
			service2R.load(null);
		} catch (IOException e2) {
			e2.printStackTrace();
		}
		
		BPDModel bpd=null;
		try {
			bpd = (new BPMN2BPD()).getBPDmodel(((BpmnDiagram)bpmnR.getContents().get(0)).getPools().get(0));
		} catch (ProviderException e1) {
			e1.printStackTrace();
		}

		((DataFlow) dfmR.getContents().get(0)).fixDfmRef(bpd);
		
		arg.put(DataFlowContrib.KEY, dfmR.getContents().get(0));
		arg.put(InitContrib.KEY, pimR.getContents().get(0));
		arg.put(PartnerContrib.KEY, ((Bindings)pmmR.getContents().get(0)).toPmm(bpd));
		arg.put(ControlFlowContrib.KEY, bpd);
		
		Production prod;
		try {
			prod = generator.generate(arg);
			outProcess(set, prod);
			
			int c=0;
			for(Definition def: prod.getWSDLs()) {
				outWsdl(set, "service"+(c++)+".wsdl", def);
			}
		} catch (BPELGenerationException e) {
			e.printStackTrace();
		}
	}
	
	private static final void outProcess(ResourceSet set, Production prod) {
		Resource out = set.createResource(URI
				.createFileURI("tmp/out/process.bpel"));
		DocumentRoot root = AbstractFactory.eINSTANCE.createDocumentRoot();
		root.setProcess(prod.getProcess());
		out.getContents().add(root);
		AbstractXMLProcessor processor = new AbstractXMLProcessor();
		try {
			processor.save(new FileOutputStream(
					new File("tmp/out/process.bpel")), out, null);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private static final void outWsdl(ResourceSet set, String name, Definition wsdl) {
		if(wsdl.eResource()!=null) {
			name=wsdl.eResource().getURI().toString();
		}
		Resource out= set.createResource(URI.createFileURI("tmp/out/"+name));
		out.getContents().add(wsdl);
		try {
			out.save(null);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}
